VMX assist is used for real mode and protected mode.
Signed-off-by: Jun Nakajima <jun.nakajima@intel.com>
Signed-off-by: Xin B Li <xin.b.li@intel.com>
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
struct domain *d = v->domain;
if (d->arch.hvm_domain.shared_page_va)
unmap_domain_page((void *)d->arch.hvm_domain.shared_page_va);
+ shadow_direct_map_clean(v);
}
destroy_vmcb(&v->arch.hvm_svm);
put_page(mfn_to_page(old_base_mfn));
}
#endif
-#if CONFIG_PAGING_LEVELS == 2
- shadow_direct_map_clean(v);
-#endif
+
/* Now arch.guest_table points to machine physical. */
v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT);
update_pagetables(v);
if ( d->arch.hvm_domain.shared_page_va )
unmap_domain_page_global(
(void *)d->arch.hvm_domain.shared_page_va);
+ shadow_direct_map_clean(v);
}
vmx_request_clear_vmcs(v);
__vmwrite(GUEST_CR4, crn | X86_CR4_PAE);
}
}
-#if CONFIG_PAGING_LEVELS == 2
- shadow_direct_map_clean(v);
-#endif
+
/*
* Now arch.guest_table points to machine physical.
*/
#if ( CONFIG_PAGING_LEVELS == 3 && !defined (GUEST_PGENTRY_32) ) || \
( CONFIG_PAGING_LEVELS == 4 && defined (GUEST_PGENTRY_32) )
+
/*
* Use GUEST_PGENTRY_32 to force PAE_SHADOW_SELF_ENTRY for L4.
*
{
struct vcpu *v = current;
struct domain *d = v->domain;
- l3_pgentry_t sl3e;
- l2_pgentry_t sl2e;
+ l3_pgentry_t sl3e, *sl3e_p;
+ l2_pgentry_t sl2e, *sl2e_p;
l1_pgentry_t sl1e;
unsigned long mfn, smfn;
struct page_info *page;
shadow_lock(d);
- __shadow_get_l3e(v, vpa, &sl3e);
+ __direct_get_l3e(v, vpa, &sl3e);
if ( !(l3e_get_flags(sl3e) & _PAGE_PRESENT) )
{
page = alloc_domheap_page(NULL);
if ( !page )
- goto fail;
+ goto nomem;
+
smfn = page_to_mfn(page);
sl3e = l3e_from_pfn(smfn, _PAGE_PRESENT);
- __shadow_set_l3e(v, vpa, &sl3e);
+
+ sl3e_p = (l3_pgentry_t *)map_domain_page(smfn);
+ memset(sl3e_p, 0, PAGE_SIZE);
+ unmap_domain_page(sl3e_p);
+
+ __direct_set_l3e(v, vpa, &sl3e);
}
- __shadow_get_l2e(v, vpa, &sl2e);
+ __direct_get_l2e(v, vpa, &sl2e);
if ( !(l2e_get_flags(sl2e) & _PAGE_PRESENT) )
{
page = alloc_domheap_page(NULL);
if ( !page )
- goto fail;
- smfn = page_to_mfn(page);
+ goto nomem;
+ smfn = page_to_mfn(page);
sl2e = l2e_from_pfn(smfn, __PAGE_HYPERVISOR | _PAGE_USER);
- __shadow_set_l2e(v, vpa, &sl2e);
+ sl2e_p = (l2_pgentry_t *)map_domain_page(smfn);
+ memset(sl2e_p, 0, PAGE_SIZE);
+ unmap_domain_page(sl2e_p);
+
+ __direct_set_l2e(v, vpa, &sl2e);
}
- __shadow_get_l1e(v, vpa, &sl1e);
+ __direct_get_l1e(v, vpa, &sl1e);
if ( !(l1e_get_flags(sl1e) & _PAGE_PRESENT) )
{
sl1e = l1e_from_pfn(mfn, __PAGE_HYPERVISOR | _PAGE_USER);
- __shadow_set_l1e(v, vpa, &sl1e);
+ __direct_set_l1e(v, vpa, &sl1e);
}
shadow_unlock(d);
fail:
return 0;
+
+nomem:
+ shadow_direct_map_clean(v);
+ domain_crash_synchronous();
}
#endif
v->arch.monitor_vtable = 0;
}
+static int
+map_p2m_entry(
+ l1_pgentry_t *l1tab, unsigned long va, unsigned long gpa, unsigned long mfn)
+{
+ unsigned long *l0tab = NULL;
+ l1_pgentry_t l1e = { 0 };
+ struct page_info *page;
+
+ l1e = l1tab[l1_table_offset(va)];
+ if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) )
+ {
+ page = alloc_domheap_page(NULL);
+ if ( !page )
+ goto fail;
+
+ if ( l0tab )
+ unmap_domain_page(l0tab);
+ l0tab = map_domain_page(page_to_mfn(page));
+ memset(l0tab, 0, PAGE_SIZE );
+ l1e = l1tab[l1_table_offset(va)] =
+ l1e_from_page(page, __PAGE_HYPERVISOR);
+ }
+ else if ( l0tab == NULL)
+ l0tab = map_domain_page(l1e_get_pfn(l1e));
+
+ l0tab[gpa & ((PAGE_SIZE / sizeof (mfn)) - 1) ] = mfn;
+
+ if ( l0tab )
+ unmap_domain_page(l0tab);
+
+ return 1;
+
+fail:
+ return 0;
+}
+
int
set_p2m_entry(struct domain *d, unsigned long pfn, unsigned long mfn,
struct domain_mmap_cache *l2cache,
struct domain_mmap_cache *l1cache)
{
- unsigned long tabpfn = pagetable_get_pfn(d->arch.phys_table);
+ unsigned long tabpfn;
l2_pgentry_t *l2, l2e;
l1_pgentry_t *l1;
struct page_info *l1page;
unsigned long va = pfn << PAGE_SHIFT;
+ int error;
+
+ if ( shadow_mode_external(d) )
+ {
+ tabpfn = pagetable_get_pfn(d->vcpu[0]->arch.monitor_table);
+ va = RO_MPT_VIRT_START + (pfn * sizeof (unsigned long));
+ }
+ else
+ {
+ tabpfn = pagetable_get_pfn(d->arch.phys_table);
+ va = pfn << PAGE_SHIFT;
+ }
ASSERT(tabpfn != 0);
ASSERT(shadow_lock_is_acquired(d));
l2 = map_domain_page_with_cache(tabpfn, l2cache);
+
+ /*
+ * The following code covers (SHM_translate | SHM_external) mode.
+ */
+
+ if ( shadow_mode_external(d) )
+ {
+ l1_pgentry_t *l1tab = NULL;
+ l2_pgentry_t l2e;
+
+ l2e = l2[l2_table_offset(va)];
+
+ ASSERT( l2e_get_flags(l2e) & _PAGE_PRESENT );
+
+ l1tab = map_domain_page(l2e_get_pfn(l2e));
+ error = map_p2m_entry(l1tab, va, pfn, mfn);
+ if ( !error )
+ domain_crash_synchronous();
+
+ unmap_domain_page(l1tab);
+ unmap_domain_page_with_cache(l2, l2cache);
+
+ return 1;
+ }
+
+ /*
+ * The following code covers SHM_translate mode.
+ */
+ ASSERT(shadow_mode_translate(d));
+
l2e = l2[l2_table_offset(va)];
if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
{
l2_pgentry_t *l2tab = NULL;
l1_pgentry_t *l1tab = NULL;
- unsigned long *l0tab = NULL;
l2_pgentry_t l2e = { 0 };
- l1_pgentry_t l1e = { 0 };
-
struct page_info *page;
- unsigned long pfn;
- int i;
+ unsigned long gpfn, mfn;
+ int error;
if ( pagetable_get_pfn(d->vcpu[0]->arch.monitor_table) )
{
list_ent = d->page_list.next;
- for ( i = 0; list_ent != &d->page_list; i++ )
+ for ( gpfn = 0; list_ent != &d->page_list; gpfn++ )
{
page = list_entry(list_ent, struct page_info, list);
- pfn = page_to_mfn(page);
+ mfn = page_to_mfn(page);
- l1e = l1tab[l1_table_offset(va)];
- if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) )
- {
- page = alloc_domheap_page(NULL);
- if ( l0tab )
- unmap_domain_page(l0tab);
- l0tab = map_domain_page(page_to_mfn(page));
- memset(l0tab, 0, PAGE_SIZE );
- l1e = l1tab[l1_table_offset(va)] =
- l1e_from_page(page, __PAGE_HYPERVISOR);
- }
- else if ( l0tab == NULL)
- l0tab = map_domain_page(l1e_get_pfn(l1e));
+ error = map_p2m_entry(l1tab, va, gpfn, mfn);
+ if ( !error )
+ domain_crash_synchronous();
- l0tab[i & ((1 << PAGETABLE_ORDER) - 1) ] = pfn;
- list_ent = frame_table[pfn].list.next;
- va += sizeof(pfn);
+ list_ent = frame_table[mfn].list.next;
+ va += sizeof(mfn);
}
if (l2tab)
unmap_domain_page(l2tab);
unmap_domain_page(l1tab);
- unmap_domain_page(l0tab);
return 1;
}
}
shadow_lock(d);
+
+ __direct_get_l2e(v, vpa, &sl2e);
- __shadow_get_l2e(v, vpa, &sl2e);
-
- if ( !(l2e_get_flags(sl2e) & _PAGE_PRESENT) )
+ if ( !(l2e_get_flags(sl2e) & _PAGE_PRESENT) )
{
page = alloc_domheap_page(NULL);
if ( !page )
- goto fail;
+ goto nomem;
smfn = page_to_mfn(page);
sl2e = l2e_from_pfn(smfn, __PAGE_HYPERVISOR | _PAGE_USER);
- __shadow_set_l2e(v, vpa, sl2e);
- }
- sple = (l1_pgentry_t *)map_domain_page(l2e_get_pfn(sl2e));
+ sple = (l1_pgentry_t *)map_domain_page(smfn);
+ memset(sple, 0, PAGE_SIZE);
+ __direct_set_l2e(v, vpa, sl2e);
+ }
+
+ if ( !sple )
+ sple = (l1_pgentry_t *)map_domain_page(l2e_get_pfn(sl2e));
+
sl1e = sple[l1_table_offset(vpa)];
if ( !(l1e_get_flags(sl1e) & _PAGE_PRESENT) )
sl1e = l1e_from_pfn(mfn, __PAGE_HYPERVISOR | _PAGE_USER);
sple[l1_table_offset(vpa)] = sl1e;
}
- unmap_domain_page(sple);
- shadow_unlock(d);
+ if (sple)
+ unmap_domain_page(sple);
+
+ shadow_unlock(d);
return EXCRET_fault_fixed;
fail:
return 0;
+
+nomem:
+ shadow_direct_map_clean(v);
+ domain_crash_synchronous();
}
if ( !(page = alloc_domheap_page(NULL)) )
goto fail;
- root = map_domain_page_global(page_to_mfn(page));
+ root = map_domain_page(page_to_mfn(page));
memset(root, 0, PAGE_SIZE);
+ unmap_domain_page(root);
v->domain->arch.phys_table = mk_pagetable(page_to_maddr(page));
- /*
- * We need to set shadow_vtable to get __shadow_set/get_xxx
- * working
- */
- v->arch.shadow_vtable = (l2_pgentry_t *) root;
- v->arch.shadow_table = mk_pagetable(0);
+
return 1;
fail:
int i;
l2_pgentry_t *l2e;
- ASSERT ( v->arch.shadow_vtable );
-
- l2e = v->arch.shadow_vtable;
+ l2e = map_domain_page(
+ pagetable_get_pfn(v->domain->arch.phys_table));
for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
{
free_domheap_page(
mfn_to_page(pagetable_get_pfn(v->domain->arch.phys_table)));
- unmap_domain_page_global(v->arch.shadow_vtable);
- v->arch.shadow_vtable = 0;
+ unmap_domain_page(l2e);
v->domain->arch.phys_table = mk_pagetable(0);
}
goto nomem;
}
}
- else
- {
- // external guests provide their own memory for their P2M maps.
- //
- ASSERT(d == page_get_owner(mfn_to_page(pagetable_get_pfn(
- d->arch.phys_table))));
- }
}
// Get rid of any shadow pages from any previous shadow mode.
if ( !(page = alloc_domheap_pages(NULL, 0, ALLOC_DOM_DMA)) )
goto fail;
- root = map_domain_page_global(page_to_mfn(page));
+ root = map_domain_page(page_to_mfn(page));
memset(root, 0, PAGE_SIZE);
root[PAE_SHADOW_SELF_ENTRY] = l3e_from_page(page, __PAGE_HYPERVISOR);
v->domain->arch.phys_table = mk_pagetable(page_to_maddr(page));
- /*
- * We need to set shadow_vtable to get __shadow_set/get_xxx
- * working
- */
- v->arch.shadow_vtable = (l2_pgentry_t *) root;
+ unmap_domain_page(root);
return 1;
-
+
fail:
return 0;
}
-static void shadow_direct_map_clean(struct vcpu *v)
+void shadow_direct_map_clean(struct vcpu *v)
{
l2_pgentry_t *l2e;
l3_pgentry_t *l3e;
int i, j;
- ASSERT ( v->arch.shadow_vtable );
+ l3e = (l3_pgentry_t *)map_domain_page(
+ pagetable_get_pfn(v->domain->arch.phys_table));
- l3e = (l3_pgentry_t *) v->arch.shadow_vtable;
-
for ( i = 0; i < PAE_L3_PAGETABLE_ENTRIES; i++ )
{
if ( l3e_get_flags(l3e[i]) & _PAGE_PRESENT )
free_domheap_page(
mfn_to_page(pagetable_get_pfn(v->domain->arch.phys_table)));
- unmap_domain_page_global(v->arch.shadow_vtable);
- v->arch.shadow_vtable = 0;
+ unmap_domain_page(l3e);
v->domain->arch.phys_table = mk_pagetable(0);
}
int shadow_set_guest_paging_levels(struct domain *d, int levels)
{
- struct vcpu *v = current;
shadow_lock(d);
- if ( shadow_mode_translate(d) &&
- !(pagetable_get_paddr(v->domain->arch.phys_table)) )
- shadow_direct_map_clean(v);
-
switch(levels) {
#if CONFIG_PAGING_LEVELS == 4
case 4:
return shadow_mode_refcounts(d);
}
-int
-set_p2m_entry(struct domain *d, unsigned long pfn, unsigned long mfn,
- struct domain_mmap_cache *l2cache,
- struct domain_mmap_cache *l1cache)
+static int
+map_p2m_entry(
+ pgentry_64_t *top_tab, unsigned long va, unsigned long gpa, unsigned long mfn)
{
- unsigned long tabpfn = pagetable_get_pfn(d->arch.phys_table);
- l2_pgentry_t *l2, l2e;
- l1_pgentry_t *l1;
- struct page_info *l1page;
- unsigned long va = pfn << PAGE_SHIFT;
+#if CONFIG_PAGING_LEVELS >= 4
+ pgentry_64_t l4e = { 0 };
+#endif
+#if CONFIG_PAGING_LEVELS >= 3
+ pgentry_64_t *l3tab = NULL;
+ pgentry_64_t l3e = { 0 };
+#endif
+ l2_pgentry_t *l2tab = NULL;
+ l1_pgentry_t *l1tab = NULL;
+ unsigned long *l0tab = NULL;
+ l2_pgentry_t l2e = { 0 };
+ l1_pgentry_t l1e = { 0 };
+ struct page_info *page;
- ASSERT(tabpfn != 0);
+#if CONFIG_PAGING_LEVELS >= 4
+ l4e = top_tab[l4_table_offset(va)];
+ if ( !(entry_get_flags(l4e) & _PAGE_PRESENT) )
+ {
+ page = alloc_domheap_page(NULL);
+ if ( !page )
+ goto nomem;
- l2 = map_domain_page_with_cache(tabpfn, l2cache);
- l2e = l2[l2_table_offset(va)];
- if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
+ l3tab = map_domain_page(page_to_mfn(page));
+ memset(l3tab, 0, PAGE_SIZE);
+ l4e = top_tab[l4_table_offset(va)] =
+ entry_from_page(page, __PAGE_HYPERVISOR);
+ }
+ else if ( l3tab == NULL)
+ l3tab = map_domain_page(entry_get_pfn(l4e));
+
+ l3e = l3tab[l3_table_offset(va)];
+#else
+ l3e = top_tab[l3_table_offset(va)];
+#endif
+ if ( !(entry_get_flags(l3e) & _PAGE_PRESENT) )
{
- l1page = alloc_domheap_page(NULL);
- if ( !l1page )
- {
- unmap_domain_page_with_cache(l2, l2cache);
- return 0;
- }
+ page = alloc_domheap_page(NULL);
+ if ( !page )
+ goto nomem;
+
+ l2tab = map_domain_page(page_to_mfn(page));
+ memset(l2tab, 0, PAGE_SIZE);
+ l3e = l3tab[l3_table_offset(va)] =
+ entry_from_page(page, __PAGE_HYPERVISOR);
+ }
+ else if ( l2tab == NULL)
+ l2tab = map_domain_page(entry_get_pfn(l3e));
- l1 = map_domain_page_with_cache(page_to_mfn(l1page), l1cache);
- memset(l1, 0, PAGE_SIZE);
- unmap_domain_page_with_cache(l1, l1cache);
+ l2e = l2tab[l2_table_offset(va)];
+ if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
+ {
+ page = alloc_domheap_page(NULL);
+ if ( !page )
+ goto nomem;
- l2e = l2e_from_page(l1page, __PAGE_HYPERVISOR);
- l2[l2_table_offset(va)] = l2e;
+ l1tab = map_domain_page(page_to_mfn(page));
+ memset(l1tab, 0, PAGE_SIZE);
+ l2e = l2tab[l2_table_offset(va)] =
+ l2e_from_page(page, __PAGE_HYPERVISOR);
+ }
+ else if ( l1tab == NULL)
+ l1tab = map_domain_page(l2e_get_pfn(l2e));
+
+ l1e = l1tab[l1_table_offset(va)];
+ if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) )
+ {
+ page = alloc_domheap_page(NULL);
+ if ( !page )
+ goto nomem;
+
+ l0tab = map_domain_page(page_to_mfn(page));
+ memset(l0tab, 0, PAGE_SIZE);
+ l1e = l1tab[l1_table_offset(va)] =
+ l1e_from_page(page, __PAGE_HYPERVISOR);
}
- unmap_domain_page_with_cache(l2, l2cache);
+ else if ( l0tab == NULL)
+ l0tab = map_domain_page(l1e_get_pfn(l1e));
- l1 = map_domain_page_with_cache(l2e_get_pfn(l2e), l1cache);
- l1[l1_table_offset(va)] = l1e_from_pfn(mfn, __PAGE_HYPERVISOR);
- unmap_domain_page_with_cache(l1, l1cache);
+ l0tab[gpa & ((PAGE_SIZE / sizeof (mfn)) - 1) ] = mfn;
+
+ if ( l2tab )
+ {
+ unmap_domain_page(l2tab);
+ l2tab = NULL;
+ }
+ if ( l1tab )
+ {
+ unmap_domain_page(l1tab);
+ l1tab = NULL;
+ }
+ if ( l0tab )
+ {
+ unmap_domain_page(l0tab);
+ l0tab = NULL;
+ }
return 1;
+
+nomem:
+
+ return 0;
+}
+
+int
+set_p2m_entry(struct domain *d, unsigned long pfn, unsigned long mfn,
+ struct domain_mmap_cache *l2cache,
+ struct domain_mmap_cache *l1cache)
+{
+ unsigned long tabpfn = pagetable_get_pfn(d->vcpu[0]->arch.monitor_table);
+ pgentry_64_t *top;
+ unsigned long va = RO_MPT_VIRT_START + (pfn * sizeof (unsigned long));
+ int error;
+
+ ASSERT(tabpfn != 0);
+ ASSERT(shadow_lock_is_acquired(d));
+
+ top = map_domain_page_with_cache(tabpfn, l2cache);
+ error = map_p2m_entry(top, va, pfn, mfn);
+ unmap_domain_page_with_cache(top, l2cache);
+
+ if ( !error )
+ domain_crash_synchronous();
+
+ return 1;
}
int
{
struct list_head *list_ent;
unsigned long va = RO_MPT_VIRT_START; /* phys_to_machine_mapping */
-
-#if CONFIG_PAGING_LEVELS >= 4
- l4_pgentry_t *l4tab = NULL;
- l4_pgentry_t l4e = { 0 };
-#endif
-#if CONFIG_PAGING_LEVELS >= 3
- l3_pgentry_t *l3tab = NULL;
- l3_pgentry_t l3e = { 0 };
-#endif
- l2_pgentry_t *l2tab = NULL;
- l1_pgentry_t *l1tab = NULL;
- unsigned long *l0tab = NULL;
- l2_pgentry_t l2e = { 0 };
- l1_pgentry_t l1e = { 0 };
-
- unsigned long pfn;
- int i;
+ pgentry_64_t *top_tab = NULL;
+ unsigned long mfn;
+ int gpa;
ASSERT ( pagetable_get_pfn(d->vcpu[0]->arch.monitor_table) );
-#if CONFIG_PAGING_LEVELS >= 4
- l4tab = map_domain_page(
+ top_tab = map_domain_page(
pagetable_get_pfn(d->vcpu[0]->arch.monitor_table));
-#endif
-#if CONFIG_PAGING_LEVELS >= 3
- l3tab = map_domain_page(
- pagetable_get_pfn(d->vcpu[0]->arch.monitor_table));
-#endif
+
list_ent = d->page_list.next;
- for ( i = 0; list_ent != &d->page_list; i++ )
+ for ( gpa = 0; list_ent != &d->page_list; gpa++ )
{
struct page_info *page;
-
page = list_entry(list_ent, struct page_info, list);
- pfn = page_to_mfn(page);
+ mfn = page_to_mfn(page);
-#if CONFIG_PAGING_LEVELS >= 4
- l4e = l4tab[l4_table_offset(va)];
- if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
- {
- page = alloc_domheap_page(NULL);
- l3tab = map_domain_page(page_to_mfn(page));
- memset(l3tab, 0, PAGE_SIZE);
- l4e = l4tab[l4_table_offset(va)] =
- l4e_from_page(page, __PAGE_HYPERVISOR);
- }
- else if ( l3tab == NULL)
- l3tab = map_domain_page(l4e_get_pfn(l4e));
-#endif
- l3e = l3tab[l3_table_offset(va)];
- if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) )
- {
- page = alloc_domheap_page(NULL);
- l2tab = map_domain_page(page_to_mfn(page));
- memset(l2tab, 0, PAGE_SIZE);
- l3e = l3tab[l3_table_offset(va)] =
- l3e_from_page(page, __PAGE_HYPERVISOR);
- }
- else if ( l2tab == NULL)
- l2tab = map_domain_page(l3e_get_pfn(l3e));
-
- l2e = l2tab[l2_table_offset(va)];
- if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
- {
- page = alloc_domheap_page(NULL);
- l1tab = map_domain_page(page_to_mfn(page));
- memset(l1tab, 0, PAGE_SIZE);
- l2e = l2tab[l2_table_offset(va)] =
- l2e_from_page(page, __PAGE_HYPERVISOR);
- }
- else if ( l1tab == NULL)
- l1tab = map_domain_page(l2e_get_pfn(l2e));
-
- l1e = l1tab[l1_table_offset(va)];
- if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) )
- {
- page = alloc_domheap_page(NULL);
- l0tab = map_domain_page(page_to_mfn(page));
- memset(l0tab, 0, PAGE_SIZE);
- l1e = l1tab[l1_table_offset(va)] =
- l1e_from_page(page, __PAGE_HYPERVISOR);
- }
- else if ( l0tab == NULL)
- l0tab = map_domain_page(l1e_get_pfn(l1e));
+ map_p2m_entry(top_tab, va, gpa, mfn);
+ list_ent = frame_table[mfn].list.next;
+ va += sizeof(mfn);
+ }
- l0tab[i & ((PAGE_SIZE / sizeof (pfn)) - 1) ] = pfn;
- list_ent = frame_table[pfn].list.next;
- va += sizeof (pfn);
+ unmap_domain_page(top_tab);
- if ( l2tab )
- {
- unmap_domain_page(l2tab);
- l2tab = NULL;
- }
- if ( l1tab )
- {
- unmap_domain_page(l1tab);
- l1tab = NULL;
- }
- if ( l0tab )
- {
- unmap_domain_page(l0tab);
- l0tab = NULL;
- }
- }
-#if CONFIG_PAGING_LEVELS >= 4
- unmap_domain_page(l4tab);
-#endif
-#if CONFIG_PAGING_LEVELS >= 3
- unmap_domain_page(l3tab);
-#endif
return 1;
}
#define SHADOW_ENCODE_MIN_MAX(_min, _max) ((((GUEST_L1_PAGETABLE_ENTRIES - 1) - (_max)) << 16) | (_min))
#define SHADOW_MIN(_encoded) ((_encoded) & ((1u<<16) - 1))
#define SHADOW_MAX(_encoded) ((GUEST_L1_PAGETABLE_ENTRIES - 1) - ((_encoded) >> 16))
-#if CONFIG_PAGING_LEVELS == 2
extern void shadow_direct_map_clean(struct vcpu *v);
-#endif
extern int shadow_direct_map_init(struct vcpu *v);
extern int shadow_direct_map_fault(
unsigned long vpa, struct cpu_user_regs *regs);
__mark_dirty(d, pagetable_get_pfn(v->arch.guest_table));
}
+static inline void
+__direct_get_l2e(
+ struct vcpu *v, unsigned long va, l2_pgentry_t *psl2e)
+{
+ l2_pgentry_t *phys_vtable;
+
+ ASSERT(shadow_mode_enabled(v->domain));
+
+ phys_vtable = map_domain_page(
+ pagetable_get_pfn(v->domain->arch.phys_table));
+
+ *psl2e = phys_vtable[l2_table_offset(va)];
+
+ unmap_domain_page(phys_vtable);
+}
+
+static inline void
+__direct_set_l2e(
+ struct vcpu *v, unsigned long va, l2_pgentry_t value)
+{
+ l2_pgentry_t *phys_vtable;
+
+ ASSERT(shadow_mode_enabled(v->domain));
+
+ phys_vtable = map_domain_page(
+ pagetable_get_pfn(v->domain->arch.phys_table));
+
+ phys_vtable[l2_table_offset(va)] = value;
+
+ unmap_domain_page(phys_vtable);
+}
+
static inline void
update_hl2e(struct vcpu *v, unsigned long va)
{
#define PAGING_L1 1UL
#define L_MASK 0xff
+#define PAE_PAGING_LEVELS 3
+
#define ROOT_LEVEL_64 PAGING_L4
#define ROOT_LEVEL_32 PAGING_L2
+#define DIRECT_ENTRY (4UL << 16)
#define SHADOW_ENTRY (2UL << 16)
#define GUEST_ENTRY (1UL << 16)
#define entry_empty() ((pgentry_64_t) { 0 })
#define entry_from_pfn(pfn, flags) \
((pgentry_64_t) { ((intpte_t)(pfn) << PAGE_SHIFT) | put_pte_flags(flags) })
+#define entry_from_page(page, flags) (entry_from_pfn(page_to_mfn(page),(flags)))
#define entry_add_flags(x, flags) ((x).lo |= put_pte_flags(flags))
#define entry_remove_flags(x, flags) ((x).lo &= ~put_pte_flags(flags))
#define entry_has_changed(x,y,flags) \
if ( flag & SHADOW_ENTRY )
{
- root_level = ROOT_LEVEL_64;
- index = table_offset_64(va, root_level);
+ root_level = ROOT_LEVEL_64;
+ index = table_offset_64(va, root_level);
le_e = (pgentry_64_t *)&v->arch.shadow_vtable[index];
}
- else /* guest entry */
+ else if ( flag & GUEST_ENTRY )
{
root_level = v->domain->arch.ops->guest_paging_levels;
- index = table_offset_64(va, root_level);
+ index = table_offset_64(va, root_level);
le_e = (pgentry_64_t *)&v->arch.guest_vtable[index];
}
+ else /* direct mode */
+ {
+ root_level = PAE_PAGING_LEVELS;
+ index = table_offset_64(va, root_level);
+ le_e = (pgentry_64_t *)map_domain_page(
+ pagetable_get_pfn(v->domain->arch.phys_table));
+ }
+
/*
* If it's not external mode, then mfn should be machine physical.
*/
#define __guest_get_l3e(v, va, sl3e) \
__rw_entry(v, va, gl3e, GUEST_ENTRY | GET_ENTRY | PAGING_L3)
+#define __direct_set_l3e(v, va, value) \
+ __rw_entry(v, va, value, DIRECT_ENTRY | SET_ENTRY | PAGING_L3)
+#define __direct_get_l3e(v, va, sl3e) \
+ __rw_entry(v, va, sl3e, DIRECT_ENTRY | GET_ENTRY | PAGING_L3)
+#define __direct_set_l2e(v, va, value) \
+ __rw_entry(v, va, value, DIRECT_ENTRY | SET_ENTRY | PAGING_L2)
+#define __direct_get_l2e(v, va, sl2e) \
+ __rw_entry(v, va, sl2e, DIRECT_ENTRY | GET_ENTRY | PAGING_L2)
+#define __direct_set_l1e(v, va, value) \
+ __rw_entry(v, va, value, DIRECT_ENTRY | SET_ENTRY | PAGING_L1)
+#define __direct_get_l1e(v, va, sl1e) \
+ __rw_entry(v, va, sl1e, DIRECT_ENTRY | GET_ENTRY | PAGING_L1)
+
+
static inline int __guest_set_l2e(
struct vcpu *v, unsigned long va, void *value, int size)
{